﻿/**
 * @file debug.c
 * @author septem (jsm920@outlook.com)
 * @brief 测试文档
 * @version 0.1
 * @date 2025-01-21
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#if defined(_WIN32) && defined(_MSC_VER)
// #pragma execution_character_set("utf-8")
#define WIN32_LEAN_AND_MEAN // 预处理器宏定义，它告诉编译器仅包含Windows SDK中最常用的函数和数据类型，从而减小编译时间和生成的可执行文件大小。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double start = 0,end = 0,cost = 0; //用于计算耗时
void __runatexit(void)
{
    end = clock();
    cost=end-start; 
    printf("\nProgram cost time:%lfms\n", cost);fflush(stdout);
}
int _runatstart(void)
{
    start = clock();
    atexit(__runatexit);
    return 0;
}
int _runatexit(void)
{
    end = clock();
    cost=end-start; 
    printf("\nProgram cost time:%lfs\n", cost/CLOCKS_PER_SEC );fflush(stdout);
    return 0;
}
typedef int  (__cdecl  *_PIFV)(void);
#pragma section(".CRT$XIY",long,read)
__declspec(allocate(".CRT$XIY")) _PIFV __xi_Y = _runatstart ;
#pragma section(".CRT$XTY",long,read)
__declspec(allocate(".CRT$XTY")) _PIFV __xt_Y = _runatexit ;
#elif defined(__linux__)
#include <stdio.h>
#include <time.h>
#include <stdlib.h> // exit()
#include <string.h>
#include <errno.h>
#include <unistd.h>
#ifdef DEBUG
// gcc 在 main 之前执行
clock_t start = 0,end = 0,cost = 0; //用于计算耗时
__attribute__ ((constructor)) void _runatstart(void) 
{
    start = clock();
}
// gcc 在 main 这后执行
__attribute__ ((destructor))void __runatexit(void)
{
    end = clock();
    cost=end-start; 
    printf("\nProgram cost time:%lfs\n", ((double)cost)/CLOCKS_PER_SEC );
}
#endif
#endif
// #include "array.h"
// #include "list.h"
// #include "tree.h"
// #include "cfg.h"
#include "mio.h"
// int printf_val(void* p, void* params, TreeTraversalCallback_t* pttc )
// {
//     printf("% 4d ", *(int*)p); fflush(stdout);
//     return 0;
// }
int printf_val(void* p)
{
    int i = *(int*)p;
    #if defined(_WIN32) && defined(_MSC_VER)
    Sleep(i * 1000);
    DebugPrint("printf_val sleep:% 4d tid:%d\n", *(int*)p ,GetCurrentThreadId()); 
    #elif defined(__linux__)
    sleep(i);
    DebugPrint("printf_val sleep:% 4d tid:%lx\n", *(int*)p, pthread_self()); 
    #endif
    
    return i + 123;
}
int main(int argc, char* argv)
{
    // // //1. 针对 array.h 中的 的测试
    // array_t* pa = ArrayMalloc(sizeof(int), 10);int k = 0;
    // for(int i = 0; i != 40; i++)
    // {
    //     (int*)ArrayPush(pa, &i);
    // }
    // array_print_positive_order_int(pa);
    // int * p = (int*)ArrayFront(pa);
    // for(int i = 0; i != ArraySize(pa)+100; i++)
    // {
    //     if(p)
    //     {
    //         printf("%d ", *p);fflush(stdout);
    //     }
    //     p = (int*)ArrayNext(pa, p);
    // }printf("\n");fflush(stdout);
    // p = (int*)ArrayBack(pa);
    // for(int i = 0; i != ArraySize(pa)+100; i++)
    // {
    //     if(p)
    //     {
    //         printf("%d ", *p);fflush(stdout);
    //     }
    //     p = (int*)ArrayPrev(pa, p);
    // }printf("\n");fflush(stdout);
    // // for(int i = 0; i != 19; i++)
    // // {
    // //     int k = -1;
    // //     (int*)ArrayPush(pa, &k);
    // // }
    // // for(int i = 21; i != 30; i++)
    // // {
    // //     (int*)ArrayPush(pa, &i);
    // // }
    // // ArrayErase(pa, 21, 19);
    // // array_print_positive_order_int(pa);
    // // int a[] = {1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021};
    // // ArrayInsert(pa, a, 0, sizeof(a)/sizeof(a[0]));
    // // array_print_positive_order_int(pa);
    // // // array_print_negative_order_int(pa);
    // // // array_print_int_by_at(pa);
    // // // array_print_int_by_at2(pa);
    // // // int s = ArraySize(pa);
    // // // for(int i = 0; i != s; i++)
    // // // {
    // // //     ArrayShift(pa);
    // // // }
    // // // array_print_positive_order_int(pa);
    // // // array_print_negative_order_int(pa);
    // ArrayFree(pa);
    // //1.1. 针对 array.h 中的 array2_t的测试
    // array2_t* pa2 = Array2Malloc(sizeof(int), 10);
    // for(int i = 0; i != 11; i ++)
    // {
    //     Array2Push(pa2, &i);
    // }
    // Array2Free(pa2);
    // // 2. 针对 list.h 的测试
    // list_t* pl = ListMalloc(sizeof(int), 10);
    // if(pl == NULL)
    // {
    //     return -1;
    // }
    // for(int i = 0; i != 100; i++)
    // {
    //     int *p = (int*)ListPush(pl, NULL); (*p) = i;
    // }
    // for(int i = 0; i != 50; i++)
    // {
    //     ListPop(pl);
    // }
    // for(int i = 0; i != 173; i++)
    // {
    //     int *p = (int*)ListUnshift(pl, NULL); (*p) = i;
    // }
    // for(int i = 0; i != 174; i++)
    // {
    //     ListShift(pl);
    // }
    // for(int i = 0; i != 100; i++)
    // {
    //     int *p = (int*)ListPush(pl, NULL); (*p) = i;
    // }
    // list_print_positive_order_int(pl);
    // int ii[] = {1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,};
    // ListInsert(pl, ListAt2(pl,101),ii,sizeof(ii)/sizeof(ii[0]));
    // ListErase(pl, ListAt2(pl,0), 101);
    // list_print_positive_order_int(pl);
    // ListFree(pl);
    // // 3. 针对 tree.h 的测试
    // btree_t* pbt = BtreeMalloc(sizeof(int), 10);
    // btreenode_t* pbtn = BtreeGetRoot(pbt);
    // *(int*)pbtn->data = 0;
    // int i = 1;
    // pbtn = BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 3;  pbtn = BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 7;   BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 8; BtreeNodeSetRight(pbt, pbtn,&i);
    // pbtn = BtreeNodeGetParent(pbtn);
    // i = 4; pbtn = BtreeNodeSetRight(pbt, pbtn,&i);
    // i = 9; BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 10; BtreeNodeSetRight(pbt, pbtn,&i);
    // pbtn = BtreeNodeGetParent(pbtn);pbtn = BtreeNodeGetParent(pbtn);
    // i = 2; pbtn =BtreeNodeSetRight(pbt, pbtn,&i);
    // i = 5;  pbtn = BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 11; BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 12; BtreeNodeSetRight(pbt, pbtn,&i);
    // pbtn = BtreeNodeGetParent(pbtn);
    // i = 6; pbtn = BtreeNodeSetRight(pbt, pbtn,&i);
    // i = 13; BtreeNodeSetLeft(pbt, pbtn,&i);
    // i = 14; BtreeNodeSetRight(pbt, pbtn,&i);
    // //            0
    // //       1          2
    // //    3    4     5     6
    // //  7  8  9 10 11 12 13 14
    // btreeiterator_t* pbti = BtreeIteratorInit(pbt, NULL);
    // BtreeIteratorTraversalPreorder(pbti, printf_val, NULL);
    // printf("\n");fflush(stdout);
    // BtreeTraversal(BtreeGetRoot(pbt), printf_val, NULL, BTREE_TRAVERSAL_PREORDER);//0 1 3 7 8 4 9 10 2 5 11 12 6 13 14 
    // printf("\n");fflush(stdout);
    // BtreeIteratorTraversalInorder(pbti, printf_val, NULL);
    // printf("\n");fflush(stdout);
    // BtreeTraversal(BtreeGetRoot(pbt), printf_val, NULL, BTREE_TRAVERSAL_INORDER); 
    // printf("\n");fflush(stdout);
    // BtreeIteratorTraversalPostorder(pbti, printf_val, NULL);
    // printf("\n");fflush(stdout);
    // BtreeTraversal(BtreeGetRoot(pbt), printf_val, NULL, BTREE_TRAVERSAL_POSTORDER); 
    // printf("\n");fflush(stdout);
    // BtreeIteratorTraversalLevelorder(pbti, printf_val, NULL);
    // printf("\n");fflush(stdout);
    // BtreeTraversal(BtreeGetRoot(pbt), printf_val, NULL, BTREE_TRAVERSAL_LEVELORDER); 
    // printf("\n");fflush(stdout);
    // BtreeIteratorUninit(pbti);
    // BtreeFree(pbt);
    // // 3.1 针对 tree.h 中的 tree_t进行的测试
    // tree_t* pt = TreeMalloc(sizeof(int), 10);
    // if(pt == NULL)
    // {
    //     return -1;
    // }
    // int i = 0;treenode_t* ptn = TreeGetRoot(pt); *(int*)(ptn)->data = i;
    // i = 1; ptn = TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 5; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 7; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // ptn = TreeGetRoot(pt);
    // i = 2; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 3; ptn = TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 8; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 9; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // ptn = TreeGetRoot(pt);
    // i = 4; ptn = TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 10; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 11; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 12; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 13; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 14; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // i = 15; TreeNodeAppendChild(pt, ptn, TreeNodeCreate(pt, &i));
    // TreeTraversal(TreeGetRoot(pt), printf_val, NULL);
    // TreeFree(pt);
    // // 4. 针对 cfg.h 的测试
    // cfg_t* pcfg = CfgMalloc(10);
    // if(pcfg == NULL)
    // {
    //     exit(-1);
    // }
    // if(-1 == CfgOpen("./src/httpd/test/httpd.cfg",pcfg))
    // {
    //     CfgFree(pcfg);
    //     return(-1);
    // }
    // if(-1 == CfgParse( pcfg ))
    // {
    //     printf("Error:CfgParse error: %d, pos:%u, line:%u\n", pcfg->diagnosis.err,pcfg->diagnosis.pos,pcfg->diagnosis.line);
    // }
    // printf("\n \n  \n   \n    \n     \n     \n" );fflush(stdout);
    // treenode_t* node = CfgRoot(pcfg);
    // for(treenode_t* node = CfgNodeChild(CfgRoot(pcfg)); node; node=CfgNodeNext(node))
    // {
    //     cfgdata_t* pcd = CfgNodeData(node);
    //     printf("node-key:%s - \n", pcd->key?pcd->key:"NULL");fflush(stdout);
    // }
    // CfgFree(pcfg);
    // // 5. 针对 mio.h 的测试
    // // 5.1 针对 mio.h 的 tcps 的测试
    mio_t* pmio = MioMalloc(10,1);
    if(pmio == NULL)
    {
        return -1;
    }
    miocontext_t* pmioc;
    // pmioc = MioTCPSOpen(pmio, MioHostIpv4("0.0.0.0"), 2404, 5);
    // if(pmioc == NULL)
    // {
    //     MioFree(pmio);
    //     return -1;
    // }
    // MioTCPSOverlapped(pmio,pmioc);
    //pmioc = MioTCPOpen(pmio,0,0,MioHostIpv4("192.168.0.100"),2405);
    // if(pmioc == NULL || -1 == MioSetBuf(pmio,pmioc, 1024))
    // {
    //     MioFree(pmio);
    //     return -1;
    // }
    // MioTCPConnect(pmio, pmioc);
    // pmioc = MioUDPOpen(pmio, MioHostIpv4("192.168.0.100"), 2406);
    // if(pmioc == NULL || -1 == MioSetBuf(pmio,pmioc, 1024) || -1 == MioUDPOverlapped(pmio,pmioc))
    // {
    //     MioFree(pmio);
    //     return -1;
    // }
    // MioUDPConnect(pmio,pmioc,MioHostIpv4("192.168.0.100"),2407); //连接对侧就可以调用 MioUDPSend2() 发送报文
    // MioUDPSetBroadcast(pmioc,1);
    // miocontext_t* pmiocTimer = MioTimerOpen(pmio);
    // MioTimerAdd(pmiocTimer, MIO_TIMER_DELAY, 3000, 3000);
    // time_t tt; time(&tt); struct tm *ptm = localtime(&tt);
    // struct tm ttm = {.tm_year=ptm->tm_year,.tm_mon=ptm->tm_mon,.tm_mday=ptm->tm_mday,
    //     .tm_hour=ptm->tm_hour,.tm_min=ptm->tm_min,.tm_sec=ptm->tm_sec,};
    // MioTimerAdd(pmiocTimer, MIO_TIMER_AT, ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min,ttm.tm_sec+2,0,2000);
    // MioTimerAdd(pmiocTimer, MIO_TIMER_YEAR, 1,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min,ttm.tm_sec);
    // MioTimerAdd(pmiocTimer, MIO_TIMER_MONTH, 1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min,ttm.tm_sec);
    // MioTimerAdd(pmiocTimer, MIO_TIMER_DAY, 100,ttm.tm_hour,ttm.tm_min,ttm.tm_sec);
    // MioTimerOverlapped(pmio,pmiocTimer);
    pmioc = MioTaskerOpen(pmio, 4);
    // #if defined(_WIN32) && defined(_MSC_VER)
    // Sleep(3000);
    // #elif defined(__linux__)
    // sleep(3);
    // #endif
    int a = 2;
    MioTaskerAdd(pmioc, printf_val,&a, 0);
    int b = 5;
    MioTaskerAdd(pmioc, printf_val,&b, 0);
    int c = 3;
    MioTaskerAdd(pmioc, printf_val,&c, 1000);
    MioTaskerOverlapped(pmio,pmioc);
    while(1)
    {
        pmioc = MioWait(pmio,1000);
        if(pmioc == MIO_EVENT_ERR)
        {
            DebugPrint("errno:%d",errno);fflush(stdout);fflush(stderr);break;
        }
        else if(pmioc == MIO_EVENT_TIMEOUT )
        {
            continue;
        }
        #ifndef NDEBUG
        else if(pmioc == MIO_EVENT_INTR ) // 防止调试中断
        {
            continue;
        }
        #endif
        switch (pmioc->type)
        {
        case MIO_TYPE_TCPS:
        {
            miocontext_t* pmiocTCPA = MioTCPSAccept(pmio, pmioc);
            if(pmiocTCPA == NULL)
            {
                break;
            }
            MioSetBuf(pmio,pmiocTCPA, 1024);
            MioTCPOverlapped(pmio,pmiocTCPA);
            MioTCPSOverlapped(pmio,pmioc);
        } break;
        case MIO_TYPE_TCP:
        {
            char* buf = NULL; int len = 0;
            if(-1 == MioTCPRecv(pmioc, &buf, &len))
            {
                MioTCPClose(pmio,pmioc);break;
            }
            if(len == 0)
            {
                MioTCPClose(pmio,pmioc);break;
            }
            buf[len - 1] = 0;
            printf("buf:%s:%d\n", buf, len);fflush(stdout);
            strcat(buf," Reply!!!\n");
            MioTCPSend(pmioc, buf, len+9);
            MioTCPOverlapped(pmio,pmioc);
        } break;
        case MIO_TYPE_TCP_CONNECTING:
        {
            switch (MioTCPConnectStatus(pmioc))
            {
            case MIO_TCP_TIMEOUT:
                printf("MioTCP connect MIO_TCP_TIMEOUT,%d",errno);fflush(stdout);
                break;
            case MIO_TCP_REFUSED:
                printf("MioTCP connect MIO_TCP_REFUSED,%d",errno);fflush(stdout);
                break;
            case MIO_TCP_NETUNREACH:
                printf("MioTCP connect MIO_TCP_NETUNREACH,%d",errno);fflush(stdout);
                break;
            default:
                MioTCPOverlapped(pmio, pmioc);
                break;
            }
        } break;
        case MIO_TYPE_UDP:
        {
            char* buf = NULL; int len = 0;unsigned int rip = 0; unsigned short rport = 0;
            if( -1 == MioUDPRecv(pmioc,&buf,&len,&rip,&rport))
            {
                MioUDPClose(pmio,pmioc);break;
            }
            if(len == 0)
            {
                MioUDPClose(pmio,pmioc);break;
            }
            buf[len - 1] = 0;
            char srip[32]={0}; MioStringIpv4(rip,srip);
            printf("rip:%s:%d-buf:%s:%d\n",srip,rport, buf, len);fflush(stdout);
            strcat(buf," Reply!!!\n");
            MioUDPSend2(pmioc, buf, len+9);
            MioUDPSend(pmioc, buf, len+9, MioHostIpv4("255.255.255.255"), 2407);
            MioUDPOverlapped(pmio,pmioc);
        }break;
        case MIO_TYPE_TIMER:
        {
            miotimer_t * pmioct = MioTimerGetFired(pmioc);
            if(pmioct)
            {
                DebugPrint("time out: %d\n", pmioct->id);
            }
            MioTimerOverlapped(pmio,pmioc);
        }break;
        case MIO_TYPE_TASKER:
        {
            miotasker_t* pmiocta = MioTaskerGetFired(pmioc);
            if(pmiocta)
            {
                DebugPrint("tasker finished,ID: %d,status:0x%04x;return: %d\n", pmiocta->id,pmiocta->status, pmiocta->ret);
            }
            MioTaskerOverlapped(pmio, pmioc);
        } break;
        default:
            break;
        }
    }
    MioFree(pmio);
    exit(0);
}
